package com.hzncc.flowable_diboot.delivery.controller;

import com.diboot.core.util.*;
import com.diboot.core.vo.JsonResult;
import com.diboot.core.vo.Pagination;
import com.diboot.core.controller.BaseCrudRestController;
import com.diboot.file.util.ExcelHelper;
import com.diboot.iam.annotation.OperationCons;
import com.diboot.iam.annotation.BindPermission;
import com.diboot.iam.annotation.Log;
import com.hzncc.flowable_diboot.common.SapResult;
import com.hzncc.flowable_diboot.contract.excel.model.FieldMappingExportModel;
import com.hzncc.flowable_diboot.delivery.dto.DeliveryFormDTO;
import com.hzncc.flowable_diboot.delivery.excel.model.DeliveryDetailExportModel;
import com.hzncc.flowable_diboot.delivery.excel.model.DeliveryFormExportModel;
import com.hzncc.flowable_diboot.delivery.vo.*;
import com.hzncc.flowable_diboot.delivery.excel.listener.DeliveryDetailImportListener;
import com.hzncc.flowable_diboot.delivery.excel.model.DeliveryDetailImportModel;
import com.hzncc.flowable_diboot.excel.service.MultiSheetExcelImportService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.hzncc.flowable_diboot.delivery.entity.DeliveryRegister;
import com.hzncc.flowable_diboot.delivery.service.DeliveryRegisterService;
import com.hzncc.flowable_diboot.delivery.dto.DeliveryRegisterDTO;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* 发货登记 相关rest接口
* @author MyName
* @version 1.0
* @date 2024-09-29
* Copyright © MyCorp
*/
@Slf4j
@RequestMapping("/delivery-register")
@BindPermission(name = "发货登记")
@RestController
public class DeliveryRegisterController extends BaseCrudRestController<DeliveryRegister> {

    @Autowired
    private DeliveryRegisterService deliveryRegisterService;

    @Resource
    private MultiSheetExcelImportService multiSheetExcelImportService;

    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = "发货单报表导出", code = OperationCons.CODE_READ)
    @GetMapping("/delivery-forms-export")
    public JsonResult<Pagination> getDeliveryFormsExport(DeliveryFormDTO queryDto,HttpServletResponse response) {
        List<String> columns = queryDto.getColumns();
        List<DeliveryFormVO> deliveryForms = deliveryRegisterService.getDeliveryForms(queryDto);
        List<DeliveryFormExportModel> deliveryFormExportModels = this.convertList(deliveryForms);
        ExcelHelper.exportExcel(response, "发货单报表.xlsx", DeliveryFormExportModel.class, columns, deliveryFormExportModels);
        return null;
    }

    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = "发货单报表查询", code = OperationCons.CODE_READ)
    @GetMapping("/delivery-forms")
    public JsonResult<?> getDeliveryForms(DeliveryFormDTO queryDto, Pagination pagination) {
        List<DeliveryFormVO> deliveryForms = deliveryRegisterService.getDeliveryForms(queryDto, pagination);
        return JsonResult.OK(deliveryForms).bindPagination(pagination);
    }

    @Log(operation = "发缺货明细导入模板下载", businessObj = "DeliveryRegister")
    @BindPermission(name = "发缺货明细示例文件下载", code = OperationCons.CODE_READ)
    @GetMapping("/detail-download-example")
    public void downloadExample(@RequestParam("type") String type, HttpServletResponse response) throws Exception{
        String fileName = "发货明细导入示例.xlsx";
        if ("1".equals(type)){
            fileName = "发货明细导入示例.xlsx";
        }else if ("2".equals(type)){
            fileName = "缺货明细导入示例.xlsx";
        }
        ExcelHelper.exportExcel(response, fileName, DeliveryDetailImportModel.class, null);
    }

    /**
     * 发货明细批量导入
     * @param
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_UPDATE)
    @BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
    @PostMapping("/detail-import")
    public JsonResult<?> detailImport(@RequestParam("file") MultipartFile file,@RequestParam Map<String,Object> params) throws Exception {
        List<DeliveryDetailImportModel> list = multiSheetExcelImportService.readSheetBySheetNo(file, DeliveryDetailImportModel.class, DeliveryDetailImportListener.class, 1,0);
        list = list.stream().filter(e -> StringUtils.isNotEmpty(e.getMaterialCode())).collect(Collectors.toList());
        List<DeliveryDetailDetailVO> result = BeanUtils.convertList(list, DeliveryDetailDetailVO.class);
        return JsonResult.OK(result);
    }

    /**
     * 发\缺货明细导出
     * @param deliveryRegisterId
     * @param type
     * @param columns
     * @param response
     * @return
     * @throws Exception
     */
    @Log(operation = "导出列表文件", businessObj = "DeliveryRegister")
    @BindPermission(name = "导出列表文件", code = OperationCons.CODE_READ)
    @GetMapping("/detail-export")
    public JsonResult detailExport(@RequestParam("deliveryRegisterId") String deliveryRegisterId,@RequestParam("type") String type, @RequestParam(value = "columns", required = false) List<String> columns,
                                   HttpServletResponse response) throws Exception{
        DeliveryRegisterVO detail = deliveryRegisterService.getDetail(deliveryRegisterId);
        List<DeliveryDetailDetailVO> detailDetailVOS = new ArrayList<>();
        String fileName = "";
        if ("1".equals(type)){
            detailDetailVOS = detail.getDeliveryDetail();
            fileName = fileName + "发货";
        }else if ("2".equals(type)){
            detailDetailVOS = detail.getOutDeliveryDetail();
            fileName = fileName + "缺货";
        }
        fileName = fileName + "明细导出" + D.today() + ".xlsx";
        if (V.isEmpty(detailDetailVOS)) {
            return null;
        }
        List<DeliveryDetailExportModel> dataList = BeanUtils.convertList(detailDetailVOS, DeliveryDetailExportModel.class);
        ExcelHelper.exportExcel(response, fileName, DeliveryDetailExportModel.class, columns, dataList);
        return null;
    }

    /**
     * SAP推送发货登记
     * @param syncDeliveryRegisterVOS
     * @returns
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_UPDATE)
    @PostMapping("/sync")
    public SapResult<?> syncDeliveryRegister(@RequestBody List<SyncDeliveryRegisterVO> syncDeliveryRegisterVOS) throws Exception {
        deliveryRegisterService.syncDeliveryRegister(syncDeliveryRegisterVOS);
        return new SapResult("S","");
    }

    /**
     * 批量补充系统类发货单
     * @param deliveryRegisterVO
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @PutMapping("/batch-project-supplement")
    public JsonResult<List<String>> batchProjectSupplement(@RequestBody DeliveryRegisterVO deliveryRegisterVO) throws Exception {
        deliveryRegisterService.batchProjectSupplement(deliveryRegisterVO);
        return JsonResult.OK();
    }

    /**
     * 批量补充系统类发货单
     * @param deliveryRegisterVO
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @PutMapping("/batch-sys-supplement")
    public JsonResult<List<String>> batchSysSupplement(@RequestBody DeliveryRegisterVO deliveryRegisterVO) throws Exception {
        deliveryRegisterService.batchSysSupplement(deliveryRegisterVO);
        return JsonResult.OK();
    }

    /**
     * 根据发货单号获取发货信息
     * @param deliveryCode
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @GetMapping("/get-delivery-info/{deliveryCode}")
    public JsonResult<DeliveryRegisterVO> getDeliveryInfoByDeliveryCode(@PathVariable("deliveryCode") String deliveryCode) throws Exception {
        DeliveryRegisterVO deliveryInfo = deliveryRegisterService.getDeliveryInfoByDeliveryCode(deliveryCode);
        return JsonResult.OK(deliveryInfo);
    }

    /**
     * 查询发货单号列表
     * @param registerType
     * @return
     * @throws Exception
     */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @GetMapping("/get-delivery-codes")
    public JsonResult<Map<String,String>> getDeliveryCodeList(@RequestParam("registerType") String registerType) throws Exception {
        Map<String,String> result = deliveryRegisterService.getDeliveryCodeList(registerType);
        return JsonResult.OK(result);
    }

    /**
    * 查询资源对象的列表VO记录
    * <p>
    * url请求参数示例: ?fieldA=abc&pageSize=20&pageIndex=1&orderBy=id
    * </p>
    * @return
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_LIST)
    @BindPermission(name = OperationCons.LABEL_LIST, code = OperationCons.CODE_READ)
    @GetMapping()
    public JsonResult<List<DeliveryRegisterVO>> getListVOMapping(DeliveryRegisterDTO queryDto, Pagination pagination) throws Exception {
//        return super.getViewObjectList(queryDto, pagination, DeliveryRegisterListVO.class);
        List<DeliveryRegisterVO> list = deliveryRegisterService.getPage(queryDto, pagination);
        return JsonResult.OK(list).bindPagination(pagination);
    }

    /**
    * 根据id查询资源对象的详情VO
    * @param id ID
    * @return
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_DETAIL)
    @BindPermission(name = OperationCons.LABEL_DETAIL, code = OperationCons.CODE_READ)
    @GetMapping("/{id}")
    public JsonResult<DeliveryRegisterVO> getDetailVOMapping(@PathVariable("id")String id) throws Exception {
//        DeliveryRegisterDetailVO detailVO = deliveryRegisterService.getViewObject(id, DeliveryRegisterDetailVO.class);
        DeliveryRegisterVO detailVO = deliveryRegisterService.getDetail(id);
        return JsonResult.OK(detailVO);
    }


    /**
    * 创建资源对象数据
    * @param deliveryRegister
    * @return JsonResult
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_CREATE)
    @BindPermission(name = OperationCons.LABEL_CREATE, code = OperationCons.CODE_WRITE)
    @PostMapping()
    public JsonResult<?> createModelMapping(@RequestBody DeliveryRegisterVO deliveryRegister) throws Exception {
        boolean success = deliveryRegisterService.saveDeliveryRegister(deliveryRegister);
        log.debug("新建数据 发货登记:{} {}", deliveryRegister.getId(), success? "成功":"失败");
        return JsonResult.OK(deliveryRegister.getId());
    }

    /**
    * 批量创建资源对象数据
    * @param deliveryRegisterList
    * @return JsonResult
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_BATCH_UPDATE)
    @BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
    @PostMapping("/batch")
    public JsonResult<?> batchCreateModelMapping(@RequestBody List<DeliveryRegister> deliveryRegisterList) throws Exception {
        boolean success = deliveryRegisterService.createEntities(deliveryRegisterList);
        log.debug("批量新建数据 发货登记 {}", success? "成功":"失败");
        return JsonResult.OK(success);
    }

    /**
    * 根据id更新资源对象
    * @param deliveryRegister
    * @return JsonResult
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_UPDATE)
    @BindPermission(name = OperationCons.LABEL_UPDATE, code = OperationCons.CODE_WRITE)
    @PutMapping("/{id}")
    public JsonResult<?> updateModelMapping(@PathVariable("id")String id, @RequestBody DeliveryRegisterVO deliveryRegister) throws Exception {
        boolean success = deliveryRegisterService.updateDeliveryRegister(deliveryRegister);
        log.debug("更新数据 发货登记:{} {}", id, success? "成功":"失败");
        return JsonResult.OK(success);
    }

    /**
    * 根据id删除资源对象
    * @param id
    * @return
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_DELETE)
    @BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_WRITE)
    @DeleteMapping("/{id}")
    public JsonResult<?> deleteModelMapping(@PathVariable("id") String id) throws Exception {
        boolean success = deliveryRegisterService.deleteDeliveryRegister(id);
        log.debug("删除数据 发货登记:{} {}", id, success? "成功":"失败");
        return JsonResult.OK(success);
    }

    /**
    * 根据ids集合删除资源对象
    * @param ids
    * @return
    * @throws Exception
    */
    @Log(operation = OperationCons.LABEL_BATCH_DELETE)
    @BindPermission(name = OperationCons.LABEL_DELETE, code = OperationCons.CODE_WRITE)
    @PostMapping("/batch-delete")
    public JsonResult<?> deleteEntityMapping(@RequestBody List<String> ids) throws Exception {
        boolean success = deliveryRegisterService.deleteDeliveryRegisterBatch(ids);
//        boolean success = deliveryRegisterService.deleteEntities(ids);
        log.debug("批量删除数据 发货登记:{} {}", ids, success? "成功":"失败");
        return JsonResult.OK(success);
    }

    private DeliveryFormExportModel convertToDeliveryFormExportModel(DeliveryFormVO deliveryFormVO) {
        DeliveryFormExportModel model = new DeliveryFormExportModel();
        // 进行属性赋值
        if (ObjectUtils.isNotEmpty(deliveryFormVO)){
            model.setSapContractCode(deliveryFormVO.getSapOrderCode())
                    .setSapOrderCode(deliveryFormVO.getSapOrderCode())
                    .setDeliveryQuantity(deliveryFormVO.getDeliveryQuantity())
                    .setDeliveryAmount(deliveryFormVO.getDeliveryAmount())
                    .setPlanDeliveryTime(deliveryFormVO.getPlanDeliveryTime())
                    .setDelaiedLabel(deliveryFormVO.getDelaiedLabel())
                    .setDelayDays(deliveryFormVO.getDelayDays())
                    .setDeliveryTime(deliveryFormVO.getDeliveryTime())
                    .setTransitCompany(deliveryFormVO.getTransitCompany())
                    .setDeliveryCode(deliveryFormVO.getDeliveryCode())
                    .setQuantity(deliveryFormVO.getQuantity())
                    .setWeight(deliveryFormVO.getWeight())
                    .setConsigneeName(deliveryFormVO.getConsigneeName())
                    .setCompleteSetLabel(deliveryFormVO.getCompleteSetLabel())
                    .setRemark(deliveryFormVO.getRemark())
                    .setInvoicedLabel(deliveryFormVO.getInvoicedLabel());
        }
        if (ObjectUtils.isNotEmpty(deliveryFormVO.getProduct())){
            model.setAccountAssignmentLabel(ObjectUtils.isNotEmpty(deliveryFormVO.getProduct().getAccountAssignmentLabel())?deliveryFormVO.getProduct().getAccountAssignmentLabel().getLabel():"")
                    .setBusinessDept(deliveryFormVO.getProduct().getBusinessDept())
                    .setSalesTerritoryLabel(ObjectUtils.isNotEmpty(deliveryFormVO.getProduct().getSalesTerritoryLabel())?deliveryFormVO.getProduct().getSalesTerritoryLabel().getLabel():"")
                    .setProvince(deliveryFormVO.getProduct().getProvince())
                    .setCity(deliveryFormVO.getProduct().getCity())
                    .setSignerLabel(deliveryFormVO.getProduct().getSignerLabel())
                    .setContractType(deliveryFormVO.getProduct().getContractType())
                    .setContactCode(deliveryFormVO.getProduct().getContractCode())
                    .setRecipientLabel(deliveryFormVO.getProduct().getRecipientLabel())
                    .setProductName(deliveryFormVO.getProduct().getOrderModel())
                    .setOrderModel(deliveryFormVO.getProduct().getOrderModel())
                    .setSupportingMachineTool(deliveryFormVO.getProduct().getSupportingMachineTool())
                    .setProductPrice(deliveryFormVO.getProduct().getProductPrice())
                    .setSignDate(deliveryFormVO.getProduct().getSignDate())
                    .setProductSeries(deliveryFormVO.getProduct().getProductSeries())
                    .setGrade(deliveryFormVO.getProduct().getGrade())
                    .setMachineToolName(ObjectUtils.isNotEmpty(deliveryFormVO.getProduct().getMachineToolTypeLabel())?deliveryFormVO.getProduct().getMachineToolTypeLabel().getLabel():"")
                    .setFinalUser(deliveryFormVO.getProduct().getFinalUser());
        }
        return model;
    }

    public List<DeliveryFormExportModel> convertList(List<DeliveryFormVO> deliveryFormVOList) {
        return deliveryFormVOList.stream()
                .map(this::convertToDeliveryFormExportModel)
                .collect(Collectors.toList());
    }

}